//! # 中间件集成测试
//!
//! 测试 rustcloud-auth 与各种 Web 框架的中间件集成功能

use std::sync::Arc;
use std::collections::HashMap;
use tokio;
use rustcloud_auth::prelude::*;
use rustcloud_auth::service::AuthServiceBuilder;

#[cfg(feature = "axum-integration")]
mod axum_integration_tests {
    use super::*;
    use rustcloud_auth::middleware::axum::{AuthMiddleware, AuthLayer, AuthExtractor, auth_middleware};
    use rustcloud_auth::middleware::MiddlewareConfig;
    use axum::{
        extract::{Request, State},
        http::{HeaderMap, Method, StatusCode, Uri},
        middleware::Next,
        response::Response,
        routing::{get, post},
        Router,
    };
    use tower::ServiceExt;

    /// 测试用的模拟认证提供者
    struct MockAuthProvider {
        should_succeed: bool,
    }

    impl MockAuthProvider {
        fn new(should_succeed: bool) -> Self {
            Self { should_succeed }
        }
    }

    #[async_trait::async_trait]
    impl rustcloud_security::auth::AuthProvider for MockAuthProvider {
        async fn authenticate(&self, context: &AuthContext) -> SecurityResult<Principal> {
            if self.should_succeed {
                // 检查是否有有效的 Authorization 头
                if let Some(auth_header) = context.headers.get("authorization") {
                    if auth_header.starts_with("Bearer valid_token") {
                        let mut principal = Principal::new(
                            "test_user".to_string(),
                            "Test User".to_string(),
                            PrincipalType::User,
                        );
                        principal = principal
                            .add_role("user".to_string())
                            .add_permission("read:posts".to_string());
                        return Ok(principal);
                    }
                }
                
                // 检查 API Key
                if let Some(api_key) = context.headers.get("x-api-key") {
                    if api_key == "valid_api_key" {
                        let mut principal = Principal::new(
                            "api_user".to_string(),
                            "API User".to_string(),
                            PrincipalType::Service,
                        );
                        principal = principal
                            .add_role("api".to_string())
                            .add_permission("api:*".to_string());
                        return Ok(principal);
                    }
                }

                Err(SecurityError::AuthenticationFailed {
                    reason: "Invalid credentials".to_string(),
                })
            } else {
                Err(SecurityError::AuthenticationFailed {
                    reason: "Authentication disabled".to_string(),
                })
            }
        }

        async fn validate_token(&self, token: &str) -> SecurityResult<bool> {
            Ok(self.should_succeed && token == "valid_token")
        }

        fn provider_type(&self) -> AuthProviderType {
            AuthProviderType::Custom("mock".to_string())
        }

        fn provider_name(&self) -> &str {
            "mock"
        }
    }

    /// 测试基础中间件功能
    #[tokio::test]
    async fn test_auth_middleware_basic() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let config = MiddlewareConfig::default();
        let middleware = AuthMiddleware::new(auth_service, config);

        // 创建模拟请求
        let uri = Uri::from_static("/api/posts");
        let method = Method::GET;
        let mut headers = HeaderMap::new();
        headers.insert("authorization", "Bearer valid_token".parse().unwrap());

        // 创建模拟的 Next 处理器
        let next = Next::new(|_: Request| async {
            Response::builder()
                .status(StatusCode::OK)
                .body("Success".to_string())
                .unwrap()
        });

        let request = Request::builder()
            .uri(&uri)
            .method(&method)
            .body("".to_string())
            .unwrap();

        // 执行中间件
        let result = middleware.handle(uri, method, headers, request, next).await;
        assert!(result.is_ok());
    }

    /// 测试认证失败场景
    #[tokio::test]
    async fn test_auth_middleware_authentication_failure() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let config = MiddlewareConfig::default();
        let middleware = AuthMiddleware::new(auth_service, config);

        // 创建无效认证的请求
        let uri = Uri::from_static("/api/posts");
        let method = Method::GET;
        let mut headers = HeaderMap::new();
        headers.insert("authorization", "Bearer invalid_token".parse().unwrap());

        let next = Next::new(|_: Request| async {
            Response::builder()
                .status(StatusCode::OK)
                .body("Success".to_string())
                .unwrap()
        });

        let request = Request::builder()
            .uri(&uri)
            .method(&method)
            .body("".to_string())
            .unwrap();

        // 执行中间件，应该失败
        let result = middleware.handle(uri, method, headers, request, next).await;
        assert!(result.is_err());
    }

    /// 测试跳过认证的路径
    #[tokio::test]
    async fn test_skip_auth_paths() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let mut config = MiddlewareConfig::default();
        config.skip_paths = vec!["/health".to_string(), "/metrics".to_string()];
        
        let middleware = AuthMiddleware::new(auth_service, config);

        // 测试健康检查路径
        let uri = Uri::from_static("/health");
        let method = Method::GET;
        let headers = HeaderMap::new(); // 没有认证头

        let next = Next::new(|_: Request| async {
            Response::builder()
                .status(StatusCode::OK)
                .body("Healthy".to_string())
                .unwrap()
        });

        let request = Request::builder()
            .uri(&uri)
            .method(&method)
            .body("".to_string())
            .unwrap();

        // 应该跳过认证，直接成功
        let result = middleware.handle(uri, method, headers, request, next).await;
        assert!(result.is_ok());
    }

    /// 测试可选认证路径
    #[tokio::test]
    async fn test_optional_auth_paths() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let mut config = MiddlewareConfig::default();
        config.optional_paths = vec!["/api/public".to_string()];
        
        let middleware = AuthMiddleware::new(auth_service, config);

        // 测试无认证的可选路径
        let uri = Uri::from_static("/api/public/posts");
        let method = Method::GET;
        let headers = HeaderMap::new(); // 没有认证头

        let next = Next::new(|_: Request| async {
            Response::builder()
                .status(StatusCode::OK)
                .body("Public content".to_string())
                .unwrap()
        });

        let request = Request::builder()
            .uri(&uri)
            .method(&method)
            .body("".to_string())
            .unwrap();

        // 应该允许访问，即使没有认证
        let result = middleware.handle(uri, method, headers, request, next).await;
        assert!(result.is_ok());
    }

    /// 测试 API Key 认证
    #[tokio::test]
    async fn test_api_key_authentication() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let config = MiddlewareConfig::default();
        let middleware = AuthMiddleware::new(auth_service, config);

        // 使用 API Key 认证
        let uri = Uri::from_static("/api/data");
        let method = Method::GET;
        let mut headers = HeaderMap::new();
        headers.insert("x-api-key", "valid_api_key".parse().unwrap());

        let next = Next::new(|_: Request| async {
            Response::builder()
                .status(StatusCode::OK)
                .body("Data".to_string())
                .unwrap()
        });

        let request = Request::builder()
            .uri(&uri)
            .method(&method)
            .body("".to_string())
            .unwrap();

        let result = middleware.handle(uri, method, headers, request, next).await;
        assert!(result.is_ok());
    }

    /// 测试授权检查
    #[tokio::test]
    async fn test_authorization_check() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .with_permission_enabled(true)
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let config = MiddlewareConfig::default();
        let middleware = AuthMiddleware::new(auth_service, config);

        // 测试有权限的请求
        let uri = Uri::from_static("/api/posts");
        let method = Method::GET;
        let mut headers = HeaderMap::new();
        headers.insert("authorization", "Bearer valid_token".parse().unwrap());

        let next = Next::new(|_: Request| async {
            Response::builder()
                .status(StatusCode::OK)
                .body("Posts".to_string())
                .unwrap()
        });

        let request = Request::builder()
            .uri(&uri)
            .method(&method)
            .body("".to_string())
            .unwrap();

        let result = middleware.handle(uri, method, headers, request, next).await;
        assert!(result.is_ok());
    }

    /// 测试上下文构建
    #[tokio::test]
    async fn test_context_building() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let config = MiddlewareConfig::default();
        let middleware = AuthMiddleware::new(auth_service, config);

        // 创建包含各种头部的请求
        let uri = Uri::from_static("/api/posts");
        let method = Method::POST;
        let mut headers = HeaderMap::new();
        headers.insert("authorization", "Bearer valid_token".parse().unwrap());
        headers.insert("user-agent", "Test Client 1.0".parse().unwrap());
        headers.insert("x-forwarded-for", "203.0.113.1, 192.168.1.1".parse().unwrap());
        headers.insert("x-session-id", "session_123".parse().unwrap());

        // 测试上下文构建功能
        let context = middleware.build_auth_context(&method, "/api/posts", &headers).unwrap();

        assert_eq!(context.method, "POST");
        assert_eq!(context.uri, "/api/posts");
        assert!(context.headers.contains_key("authorization"));
        assert!(context.headers.contains_key("user-agent"));
        assert!(context.headers.contains_key("session-id"));
        assert_eq!(context.get_client_ip(), Some("203.0.113.1"));
    }

    /// 测试服务名称提取
    #[tokio::test]
    async fn test_service_name_extraction() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let config = MiddlewareConfig::default();
        let middleware = AuthMiddleware::new(auth_service, config);

        // 测试不同路径的服务名称提取
        assert_eq!(middleware.extract_service_name("/api/user-service/users"), "user-service");
        assert_eq!(middleware.extract_service_name("/api/blog-service/posts"), "blog-service");
        assert_eq!(middleware.extract_service_name("/health"), "unknown");
        assert_eq!(middleware.extract_service_name("/api/unknown"), "unknown");
    }

    /// 测试 Axum 函数式中间件
    #[tokio::test]
    async fn test_axum_function_middleware() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("mock".to_string(), mock_provider)
                .with_default_provider("mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        // 测试处理器
        async fn test_handler() -> &'static str {
            "Protected content"
        }

        // 创建路由器并应用中间件
        let app = Router::new()
            .route("/protected", get(test_handler))
            .layer(axum::middleware::from_fn_with_state(
                auth_service.clone(),
                auth_middleware,
            ))
            .with_state(auth_service);

        // 创建测试请求
        let request = Request::builder()
            .uri("/protected")
            .method(Method::GET)
            .header("authorization", "Bearer valid_token")
            .body("".to_string())
            .unwrap();

        // 执行请求
        let response = app.oneshot(request).await.unwrap();
        assert_eq!(response.status(), StatusCode::OK);
    }
}

#[cfg(feature = "gateway-integration")]
mod gateway_integration_tests {
    use super::*;
    use rustcloud_auth::middleware::gateway::{GatewayAuthIntegration, GatewayMiddlewareAdapter};

    /// 测试用的模拟认证提供者
    struct MockAuthProvider {
        should_succeed: bool,
    }

    impl MockAuthProvider {
        fn new(should_succeed: bool) -> Self {
            Self { should_succeed }
        }
    }

    #[async_trait::async_trait]
    impl rustcloud_security::auth::AuthProvider for MockAuthProvider {
        async fn authenticate(&self, _context: &AuthContext) -> SecurityResult<Principal> {
            if self.should_succeed {
                let principal = Principal::new(
                    "gateway_user".to_string(),
                    "Gateway User".to_string(),
                    PrincipalType::User,
                );
                Ok(principal)
            } else {
                Err(SecurityError::AuthenticationFailed {
                    reason: "Gateway authentication failed".to_string(),
                })
            }
        }

        async fn validate_token(&self, _token: &str) -> SecurityResult<bool> {
            Ok(self.should_succeed)
        }

        fn provider_type(&self) -> AuthProviderType {
            AuthProviderType::Custom("gateway_mock".to_string())
        }

        fn provider_name(&self) -> &str {
            "gateway_mock"
        }
    }

    /// 测试 Gateway 集成基础功能
    #[tokio::test]
    async fn test_gateway_integration_basic() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("gateway_mock".to_string(), mock_provider)
                .with_default_provider("gateway_mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let integration = GatewayAuthIntegration::new(auth_service);

        // 创建认证上下文
        let context = AuthContext::new(
            HashMap::new(),
            "GET".to_string(),
            "/api/gateway/test".to_string(),
            Some("192.168.1.100".to_string()),
        );

        // 测试 Gateway 认证
        let result = integration.handle_gateway_auth(&context).await;
        assert!(result.is_ok());
        
        let principal = result.unwrap();
        assert!(principal.is_some());
        assert_eq!(principal.unwrap().id, "gateway_user");
    }

    /// 测试 Gateway 认证失败
    #[tokio::test]
    async fn test_gateway_authentication_failure() {
        let mock_provider = Arc::new(MockAuthProvider::new(false));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("gateway_mock".to_string(), mock_provider)
                .with_default_provider("gateway_mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let integration = GatewayAuthIntegration::new(auth_service);

        let context = AuthContext::new(
            HashMap::new(),
            "GET".to_string(),
            "/api/gateway/test".to_string(),
            Some("192.168.1.100".to_string()),
        );

        // 认证应该返回 None（认证失败但不是错误）
        let result = integration.handle_gateway_auth(&context).await;
        assert!(result.is_ok());
        assert!(result.unwrap().is_none());
    }

    /// 测试 Gateway 授权
    #[tokio::test]
    async fn test_gateway_authorization() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("gateway_mock".to_string(), mock_provider)
                .with_default_provider("gateway_mock".to_string())
                .with_permission_enabled(true)
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let integration = GatewayAuthIntegration::new(auth_service);

        let principal = Principal::new(
            "gateway_user".to_string(),
            "Gateway User".to_string(),
            PrincipalType::User,
        );

        let resource = Resource::new(
            "gateway-service".to_string(),
            "/api/gateway/data".to_string(),
            "GET".to_string(),
        );

        // 测试授权
        let result = integration.handle_gateway_authz(&principal, &resource).await;
        assert!(result.is_ok());
        assert!(result.unwrap().authorized);
    }

    /// 测试 Gateway 中间件适配器
    #[tokio::test]
    async fn test_gateway_middleware_adapter() {
        let mock_provider = Arc::new(MockAuthProvider::new(true));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("gateway_mock".to_string(), mock_provider)
                .with_default_provider("gateway_mock".to_string())
                .with_permission_enabled(true)
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let adapter = GatewayMiddlewareAdapter::new(auth_service);

        let context = AuthContext::new(
            HashMap::new(),
            "GET".to_string(),
            "/api/gateway/protected".to_string(),
            Some("192.168.1.100".to_string()),
        );

        let resource = Resource::new(
            "gateway-service".to_string(),
            "/api/gateway/protected".to_string(),
            "GET".to_string(),
        );

        // 测试完整的请求处理流程
        let result = adapter.process_request(context, resource).await;
        assert!(result.is_ok());
        assert!(result.unwrap().authorized);
    }

    /// 测试 Gateway 适配器认证失败场景
    #[tokio::test]
    async fn test_gateway_adapter_auth_failure() {
        let mock_provider = Arc::new(MockAuthProvider::new(false));
        let auth_service = Arc::new(
            AuthServiceBuilder::new()
                .add_provider("gateway_mock".to_string(), mock_provider)
                .with_default_provider("gateway_mock".to_string())
                .build()
                .await
                .expect("Failed to build auth service")
        );

        let adapter = GatewayMiddlewareAdapter::new(auth_service);

        let context = AuthContext::new(
            HashMap::new(),
            "GET".to_string(),
            "/api/gateway/protected".to_string(),
            Some("192.168.1.100".to_string()),
        );

        let resource = Resource::new(
            "gateway-service".to_string(),
            "/api/gateway/protected".to_string(),
            "GET".to_string(),
        );

        // 应该返回认证失败错误
        let result = adapter.process_request(context, resource).await;
        assert!(result.is_err());
        
        if let Err(SecurityError::AuthenticationFailed { reason }) = result {
            assert_eq!(reason, "Authentication required");
        } else {
            panic!("Expected AuthenticationFailed error");
        }
    }
}